!pr1
!lm12
!rm75
Division...................................Bob Sander-Cederlof

Remembering long division in decimal can be hard enough, but visualizing it in binary and implementing it in 6502 assembly language is awesome!  Study the following example, in which I divide an 8-bit value by a 4-bit value:

                 00110            6
             ----------         ---
       1101 ) 01010101      13 ) 85
   step A:   -0000              -78
              ----               --
               1010               7
   step B:    -0000
               ----
               10101
   step C:    - 1101
               -----
                10000
   step D:     - 1101
                -----
                  0111
   step E:       -0000
                  ----
                  0111   Remainder

In the binary version, I have not made any leaps ahead like we do in decimal.  That is, I wrote out the steps even when the quotient digit = 0.  Now let's see a program which divides an 8-bit value by a 4-bit value, just like the example above.
!np
If you think this is a clumsy program, you may be right.  Note that the loop runs five times, not four.  This is because there are five steps, as you can see in the sample division above.

The first thing the program does is to clear the quotient value.  In a 4-bit machine performing 8-bit by 4-bit division would yield a 4-bit quotient, so the top bits must be cleared.  The rest of the bits will be shifted in as the division progresses.

Next the divisor is shifted up to the high nybble position, to align with the left nybble of the dividend.  This is equivalent to step A in the example above.  The loop running from line 1200 through line 1310 performs the five partial divisions.

If the divisor is zero, or if the first partial division proves that the quotient will not fit in four bits, the program branches to ".3".  I put a BRK opcode there, but you would put an error message printer, or whatever.

To run the program above, I typed:

     :$0:55 0D N 800G 0.2

and Apple responded with:   0000- 07 0D 06

which means the remainder is 7, and the quotient is 6.

Dividing Bigger Values:

The following program will divide one two-byte value by another.  The program assumes that both the dividend and the divisor are positive values between 0 and 65535.  This program was in the original Apple II monitor ROM at $FB84, but is not present in the Apple II Plus and Apple //e ROMs.
!np
As written, this program expects the XTNDL and XTNDH bytes to be zero initially.  If they are not, a 32-bit by 16-bit division is performed; however, there is no error checking for overflow or divide fault conditions.

This program builds the quotient in the same memory locations used for the dividend.  As the dividend is shifted left to align with the divisor (opposite but equivalent to the shifting done in the previous program), empty bits appear on the right end of the dividend register.  These bit positions can be filled with the quotient as it develops.

Signed Division

With a few steps of preparation, we can divide signed values using an unsigned division subroutine.  All we need to remember is the rule learned in high school:  If numerator and denominator have the same sign, the quotient is positive; if not, the quotient is negative.




























Double Precision, Almost:

What if I want to divide a full 32-bit value by a full 16-bit value?  Both values are unsigned.  The 32-bit dividend may have a value from 0 to 4294967295, and the divisor from 0 to 65535.  All of the published programs I could find assume the leading bit of the dividend is zero, limiting the range to half of the above.
!np
If the leading bit of the dividend is significant, a one bit extension is needed in the division loop.  The following program implements a full 32/16 division.



























Line 1020 sets up a 17-step loop, because the 16-bit divisor can be shifted to 17 different positions under the 32-bit dividend.  To make it easier to understand the layout of bytes in memory, I departed from the usual low-byte-first-format in this program.  I assume this time that the most significant bytes are first:

     Dividend:   $83A $83B $83C $83D
                 msb . . . . . . lsb

     Divisor:    $83E $83F
                 msb...lsb

I also have written this program to feed the quotient bits into the least significant end of the dividend register, as the dividend shifts left.  The remainder will be found in the left two bytes of the dividend register, and the quotient in the right two bytes.

Watching It All Work:

Not being quite clairvoyant, I wanted to see what was really happening inside the 32/16 division program.  So I added some trace printouts by inserting "JSR TRACE" right after lines 1050 and 1250.  I also moved the variables into page zero, to show how much memory that can save.  (All memory references are changed from 3-byte instructions to 2-byte instructions.)









































The trace program prints first the overflow extension bit.  If this is "1" on the last line, the quotient is too large to fit in 16-bits.  TRACE next prints the four hex-digits of the quotient, and lastly the remainder.  A line is printed before each step, and at the end to show the final results.

Now here are the printouts for a few values of dividend and divisor.


